import { computed, ref, toValue } from 'vue'
import { useDraggable } from '@vueuse/core'
import type { Ref } from 'vue'
import useOffset from './useOffset'
import type { IndicatorsGraph } from '@/types'

function useWrapStyle(option: {
  wrapRef: Ref<HTMLElement | null>
  boxRef: Ref<HTMLElement | null>
  lists: Ref<IndicatorsGraph[][]>
  scale?: Ref<number>
}) {
  const { lists, boxRef, wrapRef, scale } = option

  const getLeafCount = (node?: IndicatorsGraph) => {
    let count = 0
    const iterator = (item: IndicatorsGraph) => {
      const { children } = item
      if (children) {
        children.forEach((child: IndicatorsGraph) => {
          iterator(child)
        })
      }
      else {
        count++
      }
    }

    if (node) {
      iterator(node)
    }
    return count
  }

  const wrapWidth = computed(() => {
    const counts = lists.value.map(v => getLeafCount(v[0]))
    // console.log(counts)
    const max = Math.max(...counts)
    const i = 320
    const width = (i + 2) * max
    return width
  })

  const { x, y } = useDraggable(() => wrapRef.value, {
    onMove() {
      updateWrapStyle()
    },
  })

  const left = ref('0px')
  const top = ref('0px')
  const updateWrapStyle = () => {
    const { offsetX, offsetY } = useOffset(boxRef)

    const elem = toValue(wrapRef)
    const elemRect = elem!.getBoundingClientRect()
    const elemHeight = elemRect.height
    const elemWidth = elemRect.width

    const r = elemWidth / toValue(wrapWidth)

    const m = toValue(x)
    const n = toValue(y)
    const dx = (toValue(wrapWidth) - elemWidth) / 2
    const dy = ((1 - r) * elemHeight * 0.5) / r

    const l = m !== 0 ? m - toValue(offsetX) - dx : m
    const t = n !== 0 ? n - toValue(offsetY) - dy : n

    left.value = `${l}px`
    top.value = `${t}px`
  }

  const setCenter = () => {
    const boxElem = toValue(boxRef)
    const boxElemRect = boxElem?.getBoundingClientRect()
    const boxElemWidth = boxElemRect?.width
    const boxElemHeight = boxElemRect?.height

    const elem = toValue(wrapRef)
    const elemRect = elem?.getBoundingClientRect()
    const elemHeight = elemRect?.height
    const elemWidth = elemRect?.width

    let l = 0
    let t = 0
    if (
      boxElemWidth !== undefined
      && boxElemHeight !== undefined
      && elemHeight !== undefined
      && elemWidth !== undefined
    ) {
      if (elemWidth > boxElemWidth * 1.2) {
        if (toValue(scale) !== undefined) {
          const r = boxElemWidth / elemWidth
          l = (r - 1) * 0.5 * elemWidth
          t = (r - 1) * 0.5 * elemHeight
          scale!.value = r

          left.value = `${l}px`
          top.value = `${t}px`
          return
        }
      }

      if (elemWidth < boxElemWidth) {
        l = (boxElemWidth - elemWidth) / 2
      }
      if (elemHeight < boxElemHeight) {
        t = (boxElemHeight - elemHeight) / 2
      }
    }

    left.value = `${l}px`
    top.value = `${t}px`
  }

  return {
    updateWrapStyle,
    wrapWidth,
    setCenter,
    left,
    top,
  }
}

export default useWrapStyle
